var baseStr = "\
  window.vmReady = function(callback) {\
    if (window.vm && window.vm.$options) {callback();\
    }else {document.addEventListener(\"vmready\", function() {callback(); }, false);}\
    return this; };\
  window.plusReady = function(callback) {\
    if (window.plus) {setTimeout(function() {callback();}, 0);\
    } else {document.addEventListener(\"plusready\", function() {callback();}, false);}\
    return this;};\
  window.log = function() {\
    var args = Array.prototype.slice.call(arguments);\
    var t0 = new Date();\
    args.splice(0, 0, t0);\
    plusReady(function() {\
      var t0 = args[0];\
      var t1 = new Date();\
      args[0] = '[' \
      + (window.vm && window.vm.$options && window.vm.$options.name) \
      + ':' + t0.getTime() \
      + '-' + t1.toLocaleTimeString() \
      + '(' + (t1.getTime() - t0.getTime()) + ','+ (t0.getTime() - parseInt(localStorage['$startTime']))\
      + ')]'+args[1]||''+' '+ args[2]||''+' '+args[3]||'';\
      console.log.apply(console, [args[0]]);\
    });\
   };\
   ";
if (!window.vmReady) {
  eval(baseStr);
}
Vue.later = function(fn, when, context, data) {
  when = when || 0;
  var target = Date.now() + when;
  var m = fn;
  var d = data;
  var f;
  var r;

  if (typeof fn === 'string') {
    m = context[fn];
  }

  f = function() {
    m.apply(context, [].concat(d));
  };
  var recall = function() {
    if (Date.now() > target) {
      f();
    } else {
      r = setTimeout(recall, 0);
    }
  };
  recall();
};
(function(Vue, window, document, $) {
  window.addEventListener('preload', function() {
    if (window.vm && window.vm._events) {
      window.vm.$emit('preload');
    } else {
      setTimeout(function() {
        window.vm && window.vm.$emit && window.vm.$emit('preload');
      }, 30);
    }
  });

  $.plusReady(function() {
    /**
     *
     * @param {Object} evalStr
     */
    plus.webview.Webview.prototype.evalJSReliable = function(evalStr) {
      var webview = this;
      var evalStr = evalStr || '';
      if (localStorage['$webview:' + webview.id + ':inited']) {
        webview.evalJS(evalStr);
      }
      webview.onloading = function() {
        localStorage['$webview:' + webview.id + ':inited'] = true;
        setTimeout(function() {
          webview.evalJS(baseStr + evalStr);
        }, 20)
      }
    }
  })

  Vue.util.isMobile = navigator.userAgent.match(/(iPhone|iPod|Android|ios|SymbianOS)/i)
  window.localStorageJson = function(key, value, setVal) {
    var _value = localStorage.getItem(key);
    if ((null === _value) || (('undefined' != value) && setVal)) {
      _value = JSON.stringify(value, function(k, v) {
        return typeof v == 'function' ? v.toLocaleString() : v
      }, 2);
      localStorage.setItem(key, _value);
    }
    if (!_value) {
      return null;
    }
    return JSON.parse(_value, function(k, v) {
      if (typeof v == 'string' && v.indexOf('function (') == 0) {
        return eval(k + '=' + v + ';' + k);
      }
      return v;
    });
  }

  /**
   * 默认页面跳转参数
   */
  $.$defaultOpenWindowOptions = {
    autoShow: true,
    show: {
      aniShow: 'pop-in'
    },
    styles: {
      popGesture: 'hide'
    },
    waiting: {
      autoShow: false
    },
    extras: {
      showType: 'goTo'
    }
  };

  /**
   * 5+ event(5+没提供之前我自己实现)
   * @param {type} webview
   * @param {type} eventType
   * @param {type} data
   * @returns {undefined}
   */
  Vue.$emit = function(webview, eventType /*emit args,callback*/ ) {
    var t0 = Date.now();
    var args = Array.prototype.slice.call(arguments);
    callback = args[args.length - 1]
    args.shift();
    if ($.isFunction(callback)) {
      var callbackKey = 'cb' + Date.now();
      vm.$once(callbackKey, callback);
      args[args.length - 1] = callbackKey;
    }
    if (typeof webview === 'string') {
      webview = plus.webview.getWebviewById(webview);
    }
    if (webview) {
      var evalStr = "\
			window.vmReady(function(){\
					vm.$emit.apply(vm," + JSON.stringify(args).replace(/\'/g, "\\u0027").replace(/\\/g, "\\u005c") + ");\
			});";
      webview.evalJSReliable(evalStr);
    }
  }



  Vue.dispatchVmReadyEvent = function() {
    var ev = document.createEvent('HTMLEvents');
    ev.initEvent('vmready', false, false);
    document.dispatchEvent(ev);
  }

  Vue.preload = function(options, pageOptions) {
    $.plusReady(function() {
      options.callback = options.callback || $.noop;
      Vue.later(function(options, pageOptions) {
        webView = $.preload(pageOptions);
        webView.evalJSReliable();
        Vue.later(function(options, webView) {
          options.callback(webView);
        }, options.callbackTimeout || 0, vm, [options, webView])
      }, options.timeout || 0, vm, [options, pageOptions])
    });
  }


  Vue.mixins = {
    mui: {
      attached: function() {
        $.init(this.$options.muiInitOption || {});
      },
    },
    ajax: {
      model: '',
      apiUrl: localStorage['setting:apiUrl'],
      methods: {
        setVmValueFn: function(name) {
          var self = this;
          return function(data) {
            self.$set(name, data);
          }
        },
        defaultAjaxError: function(xhr, type, errorThrown) {
          $.plusReady(function() {
            plus.nativeUI.alert('无法连接服务器');
          });
        },
        getJSON: function(model, successFn, errorFn) {
          var self = this;
          $.ajax(this.$options.apiUrl + (model || this.$options.model), {
            timeout: 1500,
            data: {
              filter: {
                where: self.$options.filterWhere || {}
              }
            },
            contentType: 'application/json',
            dataType: 'json',
            success: function(data) {
              successFn.apply(self, [data]);
            },
            error: function(xhr, type, errorThrown) {
              var errorFn = errorFn || self.defaultAjaxError;
              errorFn.apply(self, [xhr, type, errorThrown]);
            }
          });
        },
        sendJSON: function(model, data, type, successFn, errorFn) {
          var self = this;
          $.ajax(this.$options.apiUrl + (model || this.$options.model), {
            data: JSON.stringify(data),
            contentType: 'application/json',
            timeout: 2000, //超时时间设置为10秒；
            dataType: 'json',
            type: type || 'POST',
            success: function(data) {
              successFn.apply(self, [data]);
            },
            error: function(xhr, type, errorThrown) {
              var errorFn = errorFn || self.defaultAjaxError;
              errorFn.apply(self, [xhr, type, errorThrown]);
            }
          });
        },
        postJSON: function(model, data, successFn, errorFn) {
          this.sendJSON(model, data, 'POST', successFn, errorFn);
        },
        putJSON: function(model, data, successFn, errorFn) {
          this.sendJSON(model, data, 'PUT', successFn, errorFn);
        }
      }
    },
    list: {
      data: function() {
        return {
          start: 0,
          limit: 10,
          list: []
        };
      },
      events: {
        refreshList: 'loadList'
      },
      attached: function() {
        $('.mui-scroll-wrapper').scroll({
          bounce: false,
          indicators: true //是否显示滚动条
        });
        //循环初始化所有下拉刷新，上拉加载。
        $.each(document.querySelectorAll('.mui-slider-group .mui-scroll'), function(index, pullRefreshEl) {
          $(pullRefreshEl).pullToRefresh({
            down: {
              callback: function() {
                vm.start = 0;
                vm.loadList();
                this.endPullDownToRefresh();
              }
            },
            up: {
              callback: function() {
                vm.loadList();
                this.endPullUpToRefresh();
              }
            }
          });
        });
      },
      methods: {
        loadList: function(model, success, error) {
          this.getJSON(model || this.$options.model, success || this.setVmValueFn('list'), error || this.defaultAjaxError);
        },
        deleteItem: function(model, data, success, error) {
          plus.nativeUI.toast('正在删除');
          this.sendJSON((model || this.$options.model) + '/' + data.id, {}, 'DELETE', success || function() {
            plus.nativeUI.toast('已经删除');
            this.$emit('refreshList');
          }, error || this.defaultAjaxError);
        }
      }
    },
    form: {
      data: function() {
        this.$defaultItem = function() {
          return {}
        };
        return {
          item: {}
        }
      },
      events: {
        refreshItem: 'loadItem'
      },
      attached: function() {},
      methods: {
        saveItem: function(model, data, success, error, toast) {
          toast && plus.nativeUI.toast(toast);
          var data = data || this.item;
          this.sendJSON((model || this.$options.model) + '/' + (data.id || ''), data, data.id ? 'PUT' : 'POST', success || function(data) {
            plus.nativeUI.toast('Save success!');
            $.back();
          }, error || this.defaultAjaxError);
        },
        loadItem: function(model, data, success, error) {
          var itemId = (data && data.id) || this.item.id || '';
          if (itemId) {
            this.getJSON((model || this.$options.model) + '/' + itemId, success || this.setVmValueFn('item'), error || this.defaultAjaxError);
          } else {
            this.item = $.extend(this.$defaultItem(), data);
          }
        }
      }
    }
  };

  Vue.helpers = {
    //		created>>plusRead
    h5plus: {
      plusReady: function() {
        this.$currentWebViewId = window.__WebVieW_Id__;
        this.$currentWebView = plus.webview.currentWebview();
      },
      data: function() {
        return {}
      },
      created: function() {
        Vue.dispatchVmReadyEvent();
        var self = this;
        $.plusReady(function() {
          self.$options.plusReady.call(self);
          self.$emit('plusReady');
        })
        return {};
      },
    },
    page: {
      autoCloseWaiting: true,
      $startTime: Date.now(),
      attached: function() {},
      events: {
        preload: function() {},
        setValue: 'setValue',
        show: function(data) {
          this.$parentWebviewId = arguments[arguments.length - 2];
          this.$callbackKey = arguments[arguments.length - 1];
          if (this.$options.autoCloseWaiting) {
            this.closeWaiting({
              info: 'autoClose'
            });
          }
        },
      },
      methods: {
        setValue: function(pathValue) {
          this.$set(pathValue.path, pathValue.value);
        },
        closeWaiting: function(options) {
          log('closeWaiting:', JSON.stringify(options));
          var options = options || {}
          if (this.$options.autoCloseWaiting && options.info !== 'autoClose') {
            return;
          }
          plus.nativeUI.closeWaiting();
          plus.webview.currentWebview().show("pop-in", 300);
        },
        showed: function() {
          if (this.$callbackKey) {
            var args = Array.prototype.slice.call(arguments);
            args.splice(0, 0, this.$parentWebviewId, this.$callbackKey);
            Vue.$emit.apply(Vue, args);
          }

        },
        goTo: function(options, data, callback) {
          var viewOptions = $.extend($.$defaultOpenWindowOptions, options);
          var data = data || {};
          view = $.preload(viewOptions);
          if (localStorage['$webview:' + view.id + ':readyShow'] || options.showInTime) { //直接显示不触发show事件
            view.show("pop-in", 300, function() {
              callback && callback(data);
            });
          } else if (options.noWaiting) {
            Vue.$emit(view, 'show', data || {}, window.__WebVieW_Id__, callback);
          } else {
            Vue.$emit(view, 'show', data || {}, window.__WebVieW_Id__, callback);
            var waiting = plus.nativeUI.showWaiting();
            waiting.onclose = function() {
              this.closed = true
            }
            Vue.later(function() {
              if (!waiting.closed) {
                view.evalJS('vm.closeWaiting({info:"timeout"})');
              }
            }, options.timeout)
          }
        },
      }
    },
  }

  Vue.PageVm = Vue.extend({
    mixins: [Vue.mixins.mui, Vue.helpers.page, Vue.helpers.h5plus]
  });

})(Vue, window, document, mui);